using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;
using Uantek.Device.Communication.Models;
using Uantek.Device.Communication.Protocols.Interfaces;
using Uantek.Device.Communication.Services.Interfaces;
using Uantek.Model.Mas;
using Uantek.Service.Mas.IService;

namespace Uantek.Device.Communication.Services
{
    /// <summary>
    /// 设备通信服务实现
    /// </summary>
    public class DeviceCommunicationService : IDeviceCommunicationService
    {
        private readonly ILogger<DeviceCommunicationService> _logger;
        private readonly ConcurrentDictionary<string, IDeviceProtocol> _deviceProtocols;
        private readonly ConcurrentDictionary<string, DeviceStatus> _deviceStatuses;
        private readonly object _lockObject = new object();
        private bool _isStarted = false;

        public DeviceCommunicationService(ILogger<DeviceCommunicationService> logger)
        {
            _logger = logger;
            _deviceProtocols = new ConcurrentDictionary<string, IDeviceProtocol>();
            _deviceStatuses = new ConcurrentDictionary<string, DeviceStatus>();
        }

        public event EventHandler<DeviceDataModel>? DeviceDataReceived;
        public event EventHandler<DeviceStatus>? DeviceStatusChanged;

        public async Task<CommunicationResult> AddDeviceAsync(string deviceId, string protocolName, string transportType, Dictionary<string, object> connectionParameters)
        {
            try
            {
                if (_deviceProtocols.ContainsKey(deviceId))
                {
                    return new CommunicationResult { Success = false, Message = $"设备 {deviceId} 已存在" };
                }

                // 根据协议名称创建协议实例
                var protocol = CreateProtocol(protocolName, transportType, connectionParameters);
                if (protocol == null)
                {
                    return new CommunicationResult { Success = false, Message = $"不支持的协议类型: {protocolName}" };
                }

                // 订阅数据接收事件
                protocol.DataReceived += OnDeviceDataReceived;
                protocol.StatusChanged += OnDeviceStatusChanged;

                _deviceProtocols.TryAdd(deviceId, protocol);

                // 初始化设备状态
                var deviceStatus = new DeviceStatus
                {
                    DeviceId = deviceId,
                    DeviceName = deviceId,
                    IsConnected = false,
                    LastUpdateTime = DateTime.Now,
                    Status = "已添加",
                    ProtocolName = protocolName,
                    TransportType = transportType
                };
                _deviceStatuses.TryAdd(deviceId, deviceStatus);

                _logger.LogInformation($"设备 {deviceId} 添加成功，协议: {protocolName}，传输类型: {transportType}");
                return new CommunicationResult { Success = true, Message = "设备添加成功" };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"添加设备 {deviceId} 失败");
                return new CommunicationResult { Success = false, Message = $"添加设备失败: {ex.Message}" };
            }
        }

        public async Task<CommunicationResult> RemoveDeviceAsync(string deviceId)
        {
            try
            {
                if (!_deviceProtocols.TryRemove(deviceId, out var protocol))
                {
                    return new CommunicationResult { Success = false, Message = $"设备 {deviceId} 不存在" };
                }

                // 断开连接并清理资源
                await protocol.DisconnectAsync();
                protocol.DataReceived -= OnDeviceDataReceived;
                protocol.StatusChanged -= OnDeviceStatusChanged;
                protocol.Dispose();

                _deviceStatuses.TryRemove(deviceId, out _);

                _logger.LogInformation($"设备 {deviceId} 移除成功");
                return new CommunicationResult { Success = true, Message = "设备移除成功" };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"移除设备 {deviceId} 失败");
                return new CommunicationResult { Success = false, Message = $"移除设备失败: {ex.Message}" };
            }
        }

        public async Task<CommunicationResult> ConnectDeviceAsync(string deviceId)
        {
            try
            {
                if (!_deviceProtocols.TryGetValue(deviceId, out var protocol))
                {
                    return new CommunicationResult { Success = false, Message = $"设备 {deviceId} 不存在" };
                }

                var result = await protocol.ConnectAsync();
                if (result.Success && _deviceStatuses.TryGetValue(deviceId, out var status))
                {
                    status.IsConnected = true;
                    status.Status = "已连接";
                    status.LastUpdateTime = DateTime.Now;
                    DeviceStatusChanged?.Invoke(this, status);
                }

                _logger.LogInformation($"设备 {deviceId} 连接结果: {result.Message}");
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"连接设备 {deviceId} 失败");
                return new CommunicationResult { Success = false, Message = $"连接设备失败: {ex.Message}" };
            }
        }

        public async Task<CommunicationResult> DisconnectDeviceAsync(string deviceId)
        {
            try
            {
                if (!_deviceProtocols.TryGetValue(deviceId, out var protocol))
                {
                    return new CommunicationResult { Success = false, Message = $"设备 {deviceId} 不存在" };
                }

                var result = await protocol.DisconnectAsync();
                if (result.Success && _deviceStatuses.TryGetValue(deviceId, out var status))
                {
                    status.IsConnected = false;
                    status.Status = "已断开";
                    status.LastUpdateTime = DateTime.Now;
                    DeviceStatusChanged?.Invoke(this, status);
                }

                _logger.LogInformation($"设备 {deviceId} 断开结果: {result.Message}");
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"断开设备 {deviceId} 失败");
                return new CommunicationResult { Success = false, Message = $"断开设备失败: {ex.Message}" };
            }
        }

        public async Task<CommunicationResult<string>> SendCommandAsync(string deviceId, string command, Dictionary<string, object>? parameters = null)
        {
            try
            {
                if (!_deviceProtocols.TryGetValue(deviceId, out var protocol))
                {
                    return new CommunicationResult<string> { Success = false, Message = $"设备 {deviceId} 不存在" };
                }

                var result = await protocol.SendCommandAsync(command, parameters ?? new Dictionary<string, object>());
                _logger.LogDebug($"设备 {deviceId} 发送命令 {command} 结果: {result.Message}");
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"向设备 {deviceId} 发送命令 {command} 失败");
                return new CommunicationResult<string> { Success = false, Message = $"发送命令失败: {ex.Message}" };
            }
        }

        public async Task<DeviceStatus?> GetDeviceStatusAsync(string deviceId)
        {
            return await Task.FromResult(_deviceStatuses.TryGetValue(deviceId, out var status) ? status : null);
        }

        public async Task<IEnumerable<DeviceStatus>> GetAllDeviceStatusAsync()
        {
            return await Task.FromResult(_deviceStatuses.Values.ToList());
        }

        public async Task<CommunicationResult> StartAsync()
        {
            try
            {
                lock (_lockObject)
                {
                    if (_isStarted)
                    {
                        return new CommunicationResult { Success = false, Message = "服务已经启动" };
                    }
                    _isStarted = true;
                }

                _logger.LogInformation("设备通信服务启动成功");
                return await Task.FromResult(new CommunicationResult { Success = true, Message = "服务启动成功" });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "启动设备通信服务失败");
                return new CommunicationResult { Success = false, Message = $"启动服务失败: {ex.Message}" };
            }
        }

        public async Task<CommunicationResult> StopAsync()
        {
            try
            {
                lock (_lockObject)
                {
                    if (!_isStarted)
                    {
                        return new CommunicationResult { Success = false, Message = "服务未启动" };
                    }
                    _isStarted = false;
                }

                // 断开所有设备连接
                var disconnectTasks = _deviceProtocols.Values.Select(p => p.DisconnectAsync());
                await Task.WhenAll(disconnectTasks);

                _logger.LogInformation("设备通信服务停止成功");
                return new CommunicationResult { Success = true, Message = "服务停止成功" };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "停止设备通信服务失败");
                return new CommunicationResult { Success = false, Message = $"停止服务失败: {ex.Message}" };
            }
        }

        private IDeviceProtocol? CreateProtocol(string protocolName, string transportType, Dictionary<string, object> connectionParameters)
        {
            // 这里应该根据协议名称和传输类型创建具体的协议实例
            // 暂时返回null，需要在具体实现中完善
            return null;
        }

        private void OnDeviceDataReceived(object? sender, DeviceDataModel e)
        {
            DeviceDataReceived?.Invoke(this, e);
        }

        private void OnDeviceStatusChanged(object? sender, DeviceStatus e)
        {
            if (_deviceStatuses.TryGetValue(e.DeviceId, out var status))
            {
                status.IsConnected = e.IsConnected;
                status.Status = e.Status;
                status.LastUpdateTime = DateTime.Now;
                status.ErrorMessage = e.ErrorMessage;
            }
            DeviceStatusChanged?.Invoke(this, e);
        }
    }
}